package com.example.demo.utils;

import cn.hutool.core.lang.Assert;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * rsa加密工具类
 */
public class RsaUtil {

//    private static final String RSA_INSTANCE="RSA";
//
//    public static KeyPair generateKeyPair() {
//        KeyPairGenerator keyPairGenerator =null;
//        try {
//            keyPairGenerator = KeyPairGenerator.getInstance(RSA_INSTANCE);
//            keyPairGenerator.initialize(2048); // 密钥长度为2048位
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        }
//        return keyPairGenerator.generateKeyPair();
//    }
//
//
//    public static byte[] decrypt(byte[] encryptedBytes, PrivateKey privateKey){
//        byte[] result=null;
//        try{
//            Cipher cipher = Cipher.getInstance(RSA_INSTANCE);
//            cipher.init(Cipher.DECRYPT_MODE, privateKey);
//            result = cipher.doFinal(encryptedBytes);
//        }catch (NoSuchAlgorithmException | IllegalBlockSizeException | BadPaddingException | InvalidKeyException | NoSuchPaddingException e){
//            e.printStackTrace();
//        }
//        return result;
//    }
//
//
//    public static byte[] encrypt(String plainText, PublicKey publicKey) {
//        byte[] result = null;
//        try {
//            Cipher cipher = Cipher.getInstance(RSA_INSTANCE);
//            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//            result = cipher.doFinal(plainText.getBytes());
//        }catch (NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException e){
//            e.printStackTrace();
//        }
//        return result;
//    }

    /** 安全服务提供者 */
    private static final Provider PROVIDER = new BouncyCastleProvider();

    /** 密钥大小 */
    private static final int KEY_SIZE = 1024;

    public static final String KEY_ALGORITHM = "RSA";

    /**
     * 不可实例化
     */
    private void RSAUtils() {
    }

    /**
     * 生成密钥对
     *
     * @return 密钥对
     */
    public static KeyPair generateKeyPair() {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", PROVIDER);
            keyPairGenerator.initialize(KEY_SIZE, new SecureRandom());
            return keyPairGenerator.generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 加密
     *
     * @param publicKey
     *            公钥
     * @param data
     *            数据
     * @return 加密后的数据
     */
    public static byte[] encrypt(PublicKey publicKey, byte[] data) {
        Assert.notNull(publicKey);
        Assert.notNull(data);
        try {
            Cipher cipher = Cipher.getInstance("RSA", PROVIDER);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 加密
     *
     * @param publicKey
     *            公钥
     * @param text
     *            字符串
     *
     * @return Base64编码字符串
     */
    public static String encrypt(PublicKey publicKey, String text) {
        byte[] data = encrypt(publicKey, text.getBytes());
        return data != null ? Base64.encodeBase64String(data) : null;
    }

    /**
     * 解密
     *            私钥
     * @param data
     *            数据
     * @return 解密后的数据
     */
    public static byte[] decrypt(String key, byte[] data) {
        try {
            PrivateKey privateKey = getPrivateKey(key);
            Cipher cipher = Cipher.getInstance("RSA", PROVIDER);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 密钥串转privateKey
     * @param keyStr
     * @return
     * @throws Exception
     */
    public static Key stringToPrivateKey(String keyStr) throws Exception {
        byte[] keyBytes=Base64.decodeBase64(keyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }

    //获取私钥
    private static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
        //  keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        keyBytes = Base64.decodeBase64(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }


    /**
     * 私钥解密算法
     * @param cryptograph 密文
     * @return
     * @throws Exception
     */
    public static String decrypt(String privateKey,String cryptograph) throws Exception {
        Key key=stringToPrivateKey(privateKey);
        /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] b1 = Base64.decodeBase64(cryptograph);
        /** 执行解密操作 */
        byte[] b = cipher.doFinal(b1);
        return new String(b);
    }

    /**
     * RSA公钥加密
     *
     * @param str
     *            加密字符串
     * @param publicKey
     *            公钥
     * @return 密文
     * @throws Exception
     *             加密过程中的异常信息
     */
    public static String encrypt( String str, String publicKey ) throws Exception{
        //base64编码的公钥
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
        return outStr;
    }

    /**
     * <p>
     * 获取私钥
     * </p>
     * @return
     */
    public static String getPrivateKey(PrivateKey privateKey)  {
        return Base64.encodeBase64String(privateKey.getEncoded());
    }

    public static String getPublicKey(PublicKey publicKey) {
        return Base64.encodeBase64String(publicKey.getEncoded());
    }


}
